package com.lv.fast.shiro;

import com.lv.fast.constant.HttpConstant;
import com.lv.fast.constant.RestResultCodeConstant;
import com.lv.fast.constant.RestResultDescribeConstant;
import com.lv.fast.util.HttpRequestUtil;
import com.lv.fast.util.JwtUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.BearerToken;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * 后台模块shiro过滤器
 * @author lv
 * @version 1.0.0
 */
@Slf4j
public class SysFilter extends BasicHttpAuthenticationFilter {

    /**
     * 判断是否执行拦截
     * 暂定规则为除了放行跨域试探请求(请求方式为options，所以要求所有controller不能对外提供options类型的请求)
     * 其余全部拦截  被判定为需要拦截的请求会执行onAccessDenied方法
     * @param request request对象
     * @param response response对象
     * @param mappedValue mappedValue
     * @return 是否允许访问 false执行onAccessDenied
     */
    @SneakyThrows
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //放行跨域options试探请求
        return HttpConstant.REQUEST_CROS_METHOD.equalsIgnoreCase(((HttpServletRequest) request).getMethod());
    }

    /**
     * 处理被拦截的请求
     * @param request request对象
     * @param response response对象
     * @return 是否拒绝访问
     * @throws Exception 异常
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        String token = HttpRequestUtil.getToken((HttpServletRequest) request);
        if (StringUtils.isBlank(token)) {
            request.setAttribute(HttpConstant.REQUEST_ATTRIBUTE_ERROR_MESSAGE_KEY, RestResultDescribeConstant.AUTHORIZATION_TOKEN_IS_NULL);
            request.setAttribute(HttpConstant.REQUEST_ATTRIBUTE_ERROR_MESSAGE_KEY, RestResultDescribeConstant.AUTHORIZATION_TOKEN_IS_NULL);
            //处理登录失败
            request.getRequestDispatcher("/error/unauthorized").forward(request, response);
            return false;
        }
        //校验token有效性
        boolean isValid = JwtUtil.verify(token);
        if (!isValid){
            request.setAttribute(HttpConstant.REQUEST_ATTRIBUTE_ERROR_MESSAGE_KEY, RestResultCodeConstant.AUTHORIZATION_TOKEN_INVALID);
            request.setAttribute(HttpConstant.REQUEST_ATTRIBUTE_ERROR_MESSAGE_KEY, RestResultDescribeConstant.AUTHORIZATION_TOKEN_INVALID);
            //处理登录失败
            request.getRequestDispatcher("/error/unauthorized").forward(request, response);
            return false;
        }
        //执行登录
        return executeLogin(request,response);
    }

    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response){
        String token = HttpRequestUtil.getToken((HttpServletRequest) request);
        BearerToken bearerToken = new BearerToken(token);
        SecurityUtils.getSubject().login(bearerToken);
        return true;
    }
}
